package microcredit.gui.base;

import java.awt.Component;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.io.File;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;

import microcredit.gui.util.DialogUtilities;
import microcredit.gui.util.ExceptionDialog;
import microcredit.gui.util.UIUtil;

@SuppressWarnings("serial")
public abstract class BaseAction extends AbstractAction {

	protected static File defaultFolder = new File(".");
	
	private final Component parent;
	
	private boolean emulate;
	
	public BaseAction(Component parent) {
		this.parent = parent;
	}
	
	public Component getParent() {
		return parent;
	}
	
	public void setName(String name) {
		putValue(NAME, name);
	}
	
	public void setIcon(String iconName) {
		putValue(SMALL_ICON, new ImageIcon(getClass().getResource("/microcredit/icons/"+iconName)));
	}
	
	public void setAccelerator(KeyStroke stroke) {
		putValue(ACCELERATOR_KEY, stroke);
	}
	
	public KeyStroke getAccelerator() {
		return (KeyStroke)getValue(ACCELERATOR_KEY);
	}
	
	public boolean isEmulate() {
		return emulate;
	}
	
	public final void emulate(ActionEvent e) throws Throwable {
		Window w = DialogUtilities.getWindowForComponent(parent);
		setLoadingState(w, true);
		try {
			emulate = true;
			commitData(e);
			updateState();
			if (isEnabled()) {
				perform(e);
			}
		} finally {
			emulate = false;
			setLoadingState(w, false);
		}
	}
	
	private void commitData(ActionEvent e) {
		Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
		if (focusOwner != null) {
			JTable table = null;
			if (focusOwner instanceof JTable) {
				table = (JTable)focusOwner;
			} else if (focusOwner.getParent() instanceof JTable) {
				table = (JTable)focusOwner.getParent();
			}
			if (table != null) {
				if (table.getCellEditor() != null) {
					table.getCellEditor().stopCellEditing();
					table.revalidate();
				}
			}
			if (focusOwner instanceof JFormattedTextField) {
				KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
				focusOwner.requestFocus();
			}
			if (focusOwner instanceof JTextField && focusOwner.getParent() instanceof JComboBox) {
				((JComboBox) focusOwner.getParent()).setPopupVisible(false);
			}
			
		}
		UIUtil.clearValidations(parent);
	}
	
	@Override
	public final void actionPerformed(ActionEvent e) {
		try {
			Window w = DialogUtilities.getWindowForComponent(parent);
			setLoadingState(w, true);
			try {
				commitData(e);
				updateState();
				if (isEnabled()) {
					perform(e);
				}
			} finally {
				setLoadingState(w, false);
			}
		} catch (Throwable e1) {
			handleException(getParent(), e1);
		}
	}
	
	public final void handleException(Component parent, Throwable e) {
		ExceptionDialog.handleException(parent, e);
	}
	
	private void setLoadingState(Component parent, boolean loading) {
		if (parent instanceof IBaseWindow) {
			((IBaseWindow)parent).setLoadingState(loading);
		}
	}
	
	public abstract void perform(ActionEvent e) throws Throwable;

	public void updateState() throws Throwable {
		
	}
}
